package com.avo.ramcache.config;

import com.avo.ramcache.orm.Accessor;
import com.avo.ramcache.orm.MappingModel;
import com.avo.ramcache.orm.Querier;
import com.avo.ramcache.RamCacheProperties;
import org.hibernate.SessionFactory;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableConfigurationProperties({RamCacheProperties.class, DataSourceProperties.class})
public class RamCacheConfiguration {

    private final RamCacheProperties ramCacheProperties;

    public RamCacheConfiguration(RamCacheProperties ramCacheProperties) {
        this.ramCacheProperties = ramCacheProperties;
    }

    // dataSource
    @Bean
    public DataSource getDataSource(DataSourceProperties dataSourceProperties) {
        DataSourceBuilder<?> dataSourceBuilder = dataSourceProperties.initializeDataSourceBuilder();
        return dataSourceBuilder.build();
    }

    // sessionFactory
    @Bean
    public LocalSessionFactoryBean getLocalSessionFactoryBean(DataSource dataSource) {
        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setDataSource(dataSource);
        localSessionFactoryBean.setPackagesToScan("com.avo.**.entity");
        Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("current_session_context_class", "thread");
        hibernateProperties.setProperty("cache.use_second_level_cache", String.valueOf(false));
        hibernateProperties.setProperty("hibernate.dialect", "com.avo.ramcache.config.MySQL5InnoDBDialect");
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "update");
        hibernateProperties.setProperty("hibernate.show_sql", String.valueOf(true));
        hibernateProperties.setProperty("hibernate.connection.autocommit", String.valueOf(true));
        hibernateProperties.setProperty("hibernate.format_sql", String.valueOf(false));
        localSessionFactoryBean.setHibernateProperties(hibernateProperties);
        return localSessionFactoryBean;
    }

    // 查询器
    @Bean
    public Querier getQuerier(ApplicationContext context) {
        SessionFactory sessionFactory = context.getBean(SessionFactory.class);
        MappingModel mappingModel = ramCacheProperties.getMappingModel();
        return mappingModel.createQuerier(sessionFactory);
    }

    // 存储器
    @Bean
    public Accessor getAccessor(ApplicationContext context) {
        SessionFactory sessionFactory = context.getBean(SessionFactory.class);
        MappingModel mappingModel = ramCacheProperties.getMappingModel();
        return mappingModel.createAccessor(sessionFactory);
    }

    // CacheServiceManager
    @Bean("cacheServiceManager")
    public CacheServiceManagerFactory getCacheServiceManager(Accessor accessor, Querier querier) {
        CacheServiceManagerFactory cacheServiceManagerFactory = new CacheServiceManagerFactory();
        cacheServiceManagerFactory.setAccessor(accessor);
        cacheServiceManagerFactory.setQuerier(querier);
        cacheServiceManagerFactory.setConstants(ramCacheProperties.getCacheSizeMapping());
        cacheServiceManagerFactory.setEntityClasses(ramCacheProperties.getEntityClasses());
        cacheServiceManagerFactory.setPersisterConfigs(ramCacheProperties.getPersisterConfigs());
        return cacheServiceManagerFactory;
    }

}
